package com.ncloud.param.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ncloud.common.enmus.ResultEnum;
import com.ncloud.common.exception.UserException;
import com.ncloud.common.utils.JsonUtils;
import com.ncloud.common.utils.RedisUtils;
import com.ncloud.param.dao.BaseDao;
import com.ncloud.param.service.RequestCallServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created by shiqiang on 2017/6/23.
 */
@Service
public class RequestCallServerImpl implements RequestCallServer {
    private final static Logger logger = LoggerFactory.getLogger(RequestCallServerImpl.class);
    @Autowired
    private BaseDao baseDao;
    @Autowired
    private RedisUtils redisUtils;
    private static final Long expireTime=24*60*60L; //1天
    @Override
    public String getRequestUrl(JSONObject json) {
        String result ="";
        if(json == null){
            throw new UserException(ResultEnum.PARAM_ERROR.getCode(),ResultEnum.PARAM_ERROR.getMessage());
        }
        //a.system_code= and a.business_key= and a.request_type= and
        StringBuffer sql = new StringBuffer("select a.* from sys_request_call as a where a.use_tag='1'");

        if(!json.containsKey("systemCode")){
            throw new UserException(ResultEnum.PARAM_ERROR.getCode(),"systemCode 参数不存在！");
        }else{
            sql.append("and a.system_code='").append(json.getString("systemCode")).append("'");
        }
        if(!json.containsKey("businessKey")){
            throw new UserException(ResultEnum.PARAM_ERROR.getCode(),"businessKey 参数不存在！");
        }else{
            sql.append("and a.business_key='").append(json.getString("businessKey")).append("'");
        }
        /*if(!json.containsKey("requestType")){
            throw new UserException(ResultEnum.PARAM_ERROR.getCode(),"requestType 参数不存在！");
        }else {
            sql.append("and a.request_type=").append(json.getString("requestType"));
        }*/
        logger.debug("call info="+sql.toString());
        String id = json.getString("systemCode")+"_"+json.getString("businessKey");
        Map<String,Object> info = null;
        if(redisUtils.exists(id)){
            info = redisUtils.getBean(id,Map.class);
        }else{
            info = baseDao.commonQueryOne(sql.toString());
            redisUtils.set(id,info);
        }
        if(!StringUtils.isEmpty(info)){
            result = info.get("url").toString();
            //get
            if("get".equals(info.get("request_type"))){
                JSONObject param = new JSONObject();
                param.put("businessKey",info.get("business_key"));
                List<String> params = getRequestParamStr(param);
                //result = info.get("url").toString()+
                StringBuffer requestParam = new StringBuffer();
                params.stream().forEach(key -> {
                    if(json.containsKey(key)){
                        requestParam.append(key).append("=").append(json.getString(key)).append("&");
                    }
                });

                if(requestParam.lastIndexOf("&") != -1){
                    result += requestParam.deleteCharAt(requestParam.lastIndexOf("&")).toString();
                }else{
                    result += requestParam.toString();
                }
            }else if("post".equals(info.get("request_type"))){
                //psot
                if(result.contains("?")){
                    JSONObject param = new JSONObject();
                    param.put("businessKey",info.get("business_key"));
                    List<String> params = getRequestParamStr(param);
                    StringBuffer requestParam = new StringBuffer(result);
                    params.stream().forEach(key -> {
                        if(json.containsKey(key)){
                            requestParam.replace(requestParam.indexOf("?"),requestParam.indexOf("?")+1,json.getString(key));
                        }
                    });
                    result = requestParam.toString();
                }else{
                  /*对url统一处理*/
                    if(!result.endsWith("/")){
                        result += "/";
                    }
                    JSONObject param = new JSONObject();
                    param.put("businessKey",info.get("business_key"));

                /*组装url信息*/
                    List<String> params = getRequestParamStr(param);
                    StringBuffer requestParam = new StringBuffer();
                    params.stream().forEach(key -> {
                        if(json.containsKey(key)){
                            requestParam.append(json.getString(key)).append("/");
                        }
                    });
                    result += requestParam.toString();
                }

            }
        }
        logger.info("请求url路径："+result);
        return result;
    }

    public List<String> getRequestParamStr(JSONObject json) {
        String result ="";
        StringBuffer sql = new StringBuffer("select a.* from sys_request_param as a where a.use_tag='1'");

        if(!json.containsKey("businessKey")){
            throw new UserException(ResultEnum.PARAM_ERROR.getCode(),"businessKey 参数不存在！");
        }else{
            sql.append("and a.business_key='").append(json.getString("businessKey")).append("' order by a.order_seq ");
        }

        String id = "param_"+json.getString("businessKey");
        List<Map<String,Object>> list = null;
        if(redisUtils.exists(id)){
            list = redisUtils.getBean(id,List.class);
        }else{
            list = baseDao.commonQuery(sql.toString());
            redisUtils.set(id,list);
        }
        List<String> ll = list.stream().map(myMap -> myMap.get("param_name").toString()).collect(Collectors.toList());
        logger.debug("请求参数："+JSON.toJSONString(ll));
        return ll;
    }

    @Override
    public JSONObject responseBodyDeal(String json,JSONObject param) {
        logger.info("请求参数："+param.toJSONString());
        List<Map<String,Object>> responseParams = getResponseData(param);
        if(responseParams == null || responseParams.size()<=0){
            return JSON.parseObject(json);
        }else{
            JSONObject resultO = JSON.parseObject(json);
            /*获取当前接口要转换的字段配置*/
            Set keys = responseParams.stream().filter(map->map.containsKey("param_label")).map(
                    map->map.get("param_label")).distinct().collect(Collectors.toSet());
            for(Object key:keys){
                /*需要转换的字段*/
                List<Map<String,Object>> list = responseParams.stream().filter(
                        map->key.toString().equals(map.get("param_label").toString())).collect(Collectors.toList());
                for(int m=0;m<list.size();m++){
                    Map<String,Object> paramMap = list.get(m);
                    String type = paramMap.get("param_type").toString();
                    String value = paramMap.get("param_value").toString();
                    String newValue = paramMap.get("param_name").toString();
                    //JsonUtils.replaceValue(resultO,key.toString(),value,newValue);
                    logger.info("求值类型 param_type ="+type);
                    if("0".equals(type)){//json
                        resultO = JsonUtils.addValue(resultO,key.toString(),value,newValue);
                    }else if("1".equals(type)){//sql
                        //sql条件处理
                        resultO = addValue(resultO,key.toString(),value,param);
                    }
                }
            }
            logger.info("result inf {}="+resultO.toJSONString());
            return resultO;
        }
    }

    private List<Map<String,Object>> getResponseData(JSONObject json){
        String result ="";
        StringBuffer sql = new StringBuffer("select a.* from sys_response_param as a where a.use_tag='1' ");

        if(!json.containsKey("businessKey")){
            throw new UserException(ResultEnum.PARAM_ERROR.getCode(),"businessKey 参数不存在！");
        }else{
            sql.append(" and a.business_key='").append(json.getString("businessKey")).append("' order by a.param_label ");
        }
        String id = "response_param_"+json.getString("businessKey");
        List<Map<String,Object>> list = null;
        if(redisUtils.exists(id)){
            list = redisUtils.getBean(id,List.class);
        }else{
            list = baseDao.commonQuery(sql.toString());
            redisUtils.set(id,list);
        }
        return list;
    }
    /*value:sql*/
    private  JSONObject addValue(JSONObject json, String key,String value,JSONObject param){

        String custId = param.containsKey("custId")?param.getString("custId"):"";
        JSONObject result = JSON.parseObject(json.toJSONString());
        for(Map.Entry<String,Object> entry:json.entrySet()){

            Object obj = entry.getValue();
            // result.put(entry.getKey(),obj);
            if(obj instanceof JSONArray){
                result.put(entry.getKey(),addValue((JSONArray) obj,key,value,param));
            }else if(obj instanceof JSONObject){
                result.put(entry.getKey(),addValue((JSONObject)obj,key,value,param));
            }else{
                if(json.containsKey(key) && key.equals(entry.getKey())){

                    //redisKey:业务标识+字段转义+客户标识+对方设备编码
                    StringBuffer sb = new StringBuffer("LocalNode_");
                    sb.append(json.getString("businessKey")).append("_").append(key).append("_").append(custId).append(obj.toString());
                    String redisKey =sb.toString();
                    List<Map<String,Object>> list = null;
                    //暂时先不用缓存
                    /*if(redisUtils.exists(redisKey)){
                        list = redisUtils.getBean(redisKey,List.class);
                    }else{
                        list = baseDao.commonQuery(value,new Object[]{custId,obj.toString()},new int[]{java.sql.Types.VARCHAR,java.sql.Types.VARCHAR});
                        redisUtils.set(redisKey,list,expireTime);
                    }*/
                    //参数：custId , 对方设备编码信息
                    list = baseDao.commonQuery(value,new Object[]{custId,obj.toString()},new int[]{java.sql.Types.VARCHAR,java.sql.Types.VARCHAR});
                    if(list !=null && list.size()>0){
                        if(list.size()>1){
                            logger.error("sql="+value);
                            throw new UserException("8888","当前租户下的节点对应系统的多条记录，请检查！custId="+custId+";nodeParam="+obj.toString());
                        }
                        Map<String,Object> temMap = list.get(0);
                        for(Map.Entry<String,Object> innerEntry:temMap.entrySet()){
                            result.put(innerEntry.getKey(),innerEntry.getValue());
                        }

                    }else {
                        logger.error("sql="+value);
                        throw new UserException("8888","当前租户下的节点在系统中没有对应的信息，请检查！custId="+custId+";nodeParam="+obj.toString());
                    }
                }
            }
        }
        return result;
    }

    private JSONArray addValue(JSONArray array,String key,String value,JSONObject param){
        JSONArray array1 = new JSONArray();
        if(array==null) return null;
        for(int i=0;i<array.size();i++){
            Object obj = array.get(i);
            if(obj instanceof JSONArray){
                array1.add(addValue((JSONArray) obj,key,value,param));
            }else if(obj instanceof JSONObject){
                array1.add(addValue((JSONObject)obj,key,value,param));
            }else{
                array1.add(obj);
            }
        }
        return array1;
    }
}
